<?php

require_once(BaseConfig::LoadClass('vars.class.php'));

/**
 * Arreglo para verificar la eficiencia del cachador y buscar posibles consultas 
 * para cachar
**/
$__arrGConsultasParaCache = array();

/**
 * Clase que maneja las conexiones a la base de datos.
 *
 * Esta clase es solo la base. Se tiene que extender para definir las funciones
 * que usará para conectarse y para ejecutar consultas.
 * 
 * Cada objeto creado hace una nueva conexion a la BD
 */
class Conecta_Base {
  /**
   * @var Array
   */
  var $arrResultado;
  var $EOF         ;
  
  /**
   * Servidor al que se haran las consultas
   * @var string
   */
  var $strDBServer;
  
  /**
   * Usuario que se conecta a la base de datos
   * @var string
   */
  var $strDBUser  ;
  
  /**
   * Password del usuario para conectarse a la base de datos
   * @var string
   */
  var $strDBPass  ;
  
  /**
   * Nombre de la base de datos a donde se hace la conexion
   * @var string
   */
  var $strDBName  ;
  
  /**
   * Tipo de conexion (Como Mysql, Postgre, etc)
   * 
   * @var string
   */
  var $strTipoConexion;

//  var $rsConeccionServidor   ;
//  var $rsConeccionDB         ;
  var $rsResultadoConsulta   ;
  var $strUtimaConsulta      ;
  var $bolConsultaCahce      ;
  var $intIndiceConsultaCache;
  
  function __db_connect($strGDBServer = "", $strGDBUser = "", $strGDBPass = "", $strGDBName = "") {
    Variables::DebugBacktrace("Debe implementar esta funcion");
  }
  
  function __db_query($strConsulta) {
    Variables::DebugBacktrace("Debe implementar esta funcion");
  }
  
  function __db_num_rows() {
    Variables::DebugBacktrace("Debe implementar esta funcion");
  }
  
  function __db_insert_id() {
    Variables::DebugBacktrace("Debe implementar esta funcion");
  }
  
  function __db_fetch_assoc($rsResCon) {
    Variables::DebugBacktrace("Debe implementar esta funcion");
  }

  /**
   * Constructor. Si no puede conectarse al servidor de BD o a la BD en si termina el programa.
   * 
   * @global String $strGDBServer Servidor de la base de datos
   * @global String $strGDBName   Nombre de la base de datos
   * @global String $strGDBUser   Usuario de la base de datos
   * @global String $strGDBPass   Password de la base de datos
   */
  function Conecta_Base($strDBServer = "", $strDBName = "", $strDBUser = "", $strDBPass = "") {
    global $strGDBServer, $strGDBName, $strGDBUser, $strGDBPass;
    
    if($strDBServer) { $this->strDBServer = $strDBServer ; } else { $this->strDBServer = $strGDBServer; }
    if($strDBUser  ) { $this->strDBUser   = $strDBUser   ; } else { $this->strDBUser   = $strGDBUser  ; }
    if($strDBPass  ) { $this->strDBPass   = $strDBPass   ; } else { $this->strDBPass   = $strGDBPass  ; }
    if($strDBName  ) { $this->strDBName   = $strDBName   ; } else { $this->strDBName   = $strGDBName  ; }
    
    $this->arrResultado           = Array();
    $this->EOF                    = true;
    $this->strUtimaConsulta       = '';
    $this->rsResultadoConsulta    = null;
    $this->__db_connect($this->strDBServer, $this->strDBUser, $this->strDBPass, $this->strDBName);
    $this->bolConsultaCahce       = false;
    $this->intIndiceConsultaCache = -1;
  }

  /**
   * Mandar una consulta a la base de datos.
   *
   * @uses Conecta::MoveNext()
   *
   * @param String  $strConsulta     Consulta a ejecutar
   * @param boolean $bolForceNoCache Si se va a forzar la consulta (No verificar cache)
   */
  function Consulta($strConsulta, $bolForceNoCache = false) {
    //*
    global $bolGLogQuery;
    global $bolGQueryCacheTest;
    global $__arrGConsultasParaCache;
    if($bolGLogQuery) {
      echo $strConsulta . "<br />";
      
//      $hndLogConsulta = fopen('files/logc.txt', 'a+');
//      fprintf($hndLogConsulta, "%s : %s\n", date("Y-m-d H:i:s"), $strConsulta);
//      fclose($hndLogConsulta);
    }
    // */
    $this->strUtimaConsulta    = $strConsulta;
    
    if($bolGQueryCacheTest) {
      if(!isset($__arrGConsultasParaCache[strtolower($strConsulta)])) {
        $__arrGConsultasParaCache[strtolower($strConsulta)] = array("num" => 0);
      }
      $__arrGConsultasParaCache[strtolower($strConsulta)]["num"]++;
    }
    
    if($bolForceNoCache || !BaseConfig::IsCached($strConsulta)) {
      $fltMicroTime = microtime(true);
      $this->rsResultadoConsulta    = $this->__db_query($this->strUtimaConsulta);
      
      if($bolGQueryCacheTest) {
        $__arrGConsultasParaCache[strtolower($strConsulta)]["times"][] = microtime(true) - $fltMicroTime;
      }
      
      $this->bolConsultaCahce       = false;
      $this->intIndiceConsultaCache = -1;
    } else {
      $this->bolConsultaCahce       = true ;
      $this->rsResultadoConsulta    = BaseConfig::ReturnCache($strConsulta);
      if($bolGQueryCacheTest) {
        $__arrGConsultasParaCache[strtolower($strConsulta)]["caches"]++;
      }
      $this->intIndiceConsultaCache = -1;
    }
    $this->MoveNext();
  }

  /**
   * Funcion que regresa el número de renglones (rows) que generó la consulta
   *
   * @return int Numero de renglones en la consulta
   */
  function NumRows() {
    if($this->bolConsultaCahce) {
      return count($this->rsResultadoConsulta);
    } else {
      return $this->__db_num_rows();
    }
  }

  /**
   * Función que obtiene TODOS los resultados en un arreglo, algo como $arrRes[] = mysql_fetch_assoc();
   *
   * @return array
   */
  function GetCompleteRes() {
    if($this->bolConsultaCahce) {
      return $this->rsResultadoConsulta;
    }
    
    $arrRes = array();
    while(!$this->EOF) {
      $arrRes[] = $this->GetColumn();
      $this->MoveNext();
    }

    return $arrRes;
  }

  /**
   * Función que se mueve al siguiente resultado de la consulta.
   *
   * Si la consulta no envia resultados (Como un update, un delete o algo así) o si ya no hay resultados, se pone EOF como true
   */
  function MoveNext() {
    if($this->bolConsultaCahce) {
      $this->intIndiceConsultaCache++;
      if($this->NumRows() <= $this->intIndiceConsultaCache) {
        $this->EOF = true;
        return;
      }
      
      $this->EOF          = false;
      $this->arrResultado = $this->rsResultadoConsulta[$this->intIndiceConsultaCache];
    }
    
    if(($this->rsResultadoConsulta === false) || ($this->rsResultadoConsulta === true)) {
      $this->EOF = true;
      return;
    }

    $this->arrResultado = $this->__db_fetch_assoc($this->rsResultadoConsulta);

    if(is_array($this->arrResultado)) {
      $this->EOF = false;
    } else {
      $this->EOF = true;
    }
  }

  /**
   * Función que regresa el valor de una columna para la fila actual.
   * 
   * @param  String $strCampo columna que se quiere saber su valor
   * @return String Valor de la columna
   */
  function Field($strCampo) {
    if(isset($this->arrResultado[$strCampo])) {
      return $this->arrResultado[$strCampo];
    } else {
      return "";
    }
  }

  /**
   * Función que regresa la columna completa de resultados
   *
   * @return Array La columna de los resultados actuales de la consulta
   */
  function GetColumn() {
    return $this->arrResultado;
  }
  
  /**
   * Función que obtiene el último ID insertado
   *
   * @return int el ID insertado, 0 si no se insertó un ID, false en caso de error
   */
  function GetInsertedID() {
    // Por obvias razones no se puede cachar un insert, y menos hacer un query del id insertado
    if($this->bolConsultaCahce) {
      Variables::DebugBacktrace("No se puede cachar un INSERT");
    }
    
    return $this->__db_insert_id();
  }
  
  static function GetTimes() {
    global $__arrGConsultasParaCache;
    prent_r($__arrGConsultasParaCache);
  }
}

?>